import { MdxTemplate, BlockQuote } from '../../components/mdx';
import { LINKS } from '../../constants/links';
import MdxLayout from '../../app/MdxLayout';

<MdxLayout>
  <MdxTemplate
    pubdate={'2023-11-03'}
    metaTitle={'TS. Какая польза от записи `const a = [1, 2] as const`?'}
    title={<>TS. Какая польза от записи <code>const a = [1, 2] as const</code>?</>}
    ogCanonicalUrl={LINKS.articles.tsAsConst.link}
    description={'Ответ на вопрос: Что такое конструкция `const args = [8, 5] as const;`. Зачем она нужна?'}
  >
    Сегодня в PR от коллеги столкнулся с подобной записью `const args = [8, 5] as const;` и меня удивило наличие `as const`.

    Что же это за конструкция и в чём её польза?

    Начнём с простого примера на TS:

    ```ts
    const args2 = [8, 5];
    const args = [8, 5] as const;
    const angle = Math.atan2(...args);
    console.log(angle);
    ```

    Этот код скомпилируется в такой d.ts код:

    ```ts
    declare const args2: number[];
    declare const args: readonly [8, 5];
    declare const angle: number;
    ```

    И в такой JS код:

    ```js
    "use strict";
    const args2 = [8, 5];
    const args = [8, 5];
    const angle = Math.atan2(...args);
    console.log(angle);
    ```

    Как видно из результатов компиляции, разница между `args2` и `args` есть только в `d.ts`.

    В чём лаключается разница?

    - `args2` - можно изменять, т.е.выполнить команду push и ей подобные.
    - `args` - изменение заблокировано

    Есть тут ещё как минимум одна польза,
    её видно при попытке выполнить такой код `Math.atan2(...args)`
    и такой `Math.atan2(...args2)`.

    Во втором случае мы получим ошибку от компилятора:

    <BlockQuote>
      A spread argument must either have a tuple type or be passed to a rest parameter.
    </BlockQuote>

    Что дословно переводится так:

    <BlockQuote>
      Аргумент распространения должен иметь тип кортежа или передаваться в параметр rest.
    </BlockQuote>

    Понимается это так:

    <BlockQuote>Количество передаваемых аргументов отличается от ожидаемого количества аргументов.</BlockQuote>

    Весьма странное замечание, но `as const` приходит к нам на помощь.

    <strong>Подведём итоги</strong> того что полезного от можно получить `as const`:

    1. Позволяет сделать `readonly` константу
    2. Устраняет ошибку при передаче массива в функцию при помощи спред оператора

    <hr />

    Больше примеров <a target="_blank" href="https://bobbyhadz.com/blog/typescript-spread-argument-must-either-have-tuple-type">тут</a>
  </MdxTemplate>
</MdxLayout>
